package com.heima;

import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
import javafx.scene.control.TextInputControl;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.scene.image.WritableImage;
import java.awt.image.BufferedImage;


import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import javafx.scene.control.Alert;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import java.util.stream.Collectors;

// 在模块化项目中，SwingFXUtils 可能需要通过特定配置才能使用
public class Main extends Application {
    private Canvas canvas;
    private Color currentColor = Color.BLACK;
    private String currentText = "";
    private ShapeType currentShapeType = ShapeType.RECTANGLE;
    private List<DrawableShape> shapes = new ArrayList<>();
    private DrawableShape selectedShape = null;
    private double dragStartX, dragStartY;
    private List<DrawableShape> multiSelection = new ArrayList<>();
    private boolean isMultiSelecting = false;
    private double selectionStartX, selectionStartY;
    private double selectionEndX, selectionEndY;
    private ConnectionManager connectionManager = new ConnectionManager();
    private LineStyle currentLineStyle = LineStyle.STRAIGHT;
    private Color lineColor = Color.BLACK;
    private double lineWidth = 2.0;
    private boolean isCreatingConnection = false;
    private ConnectionPoint connectionStartPoint = null; // 新增：记录起始连接点
    private ConnectionLine selectedLine = null; // 新增：记录选中的连接线
    private ColorPicker lineColorPicker; // 新增：连接线颜色选择器
    private ComboBox<LineStyle> lineStyleComboBox; // 新增：连接线样式选择器
    private Slider lineWidthSlider; // 新增：连接线粗细调节滑块

    // 用于复制粘贴的剪贴板
    private List<DrawableShape> clipboard = new ArrayList<>();
    
    // 操作历史记录
    private Stack<Operation> history = new Stack<>();
    private Stack<Operation> redoStack = new Stack<>();
    
    // 是否允许创建形状的标志位
    private boolean shouldCreateShape = false;
    
    // 是否发生过有效拖动
    private boolean wasDragging = false;
    
    @Override
    public void start(Stage primaryStage) {
        BorderPane root = new BorderPane();

        // 初始化工具栏
        VBox toolbar = createToolBar();
        root.setTop(toolbar);

        // 初始化图形库面板
        VBox shapeLibrary = createShapeLibrary();
        root.setLeft(shapeLibrary);

        // 初始化画布
        canvas = new Canvas(800, 600);
        setupCanvasEvents();
        
        // 设置焦点以便接收键盘事件
        canvas.setFocusTraversable(true);
        canvas.requestFocus(); // 请求初始焦点

        root.setCenter(canvas);
        
        Scene scene = new Scene(root, 1000, 700);
        primaryStage.setTitle("Flowchart Editor");
        primaryStage.setScene(scene);
        primaryStage.show();

        // 添加监听器确保场景加载后焦点仍在画布上
        scene.setOnKeyPressed(e -> canvas.requestFocus());
    }
    
    /**
     * 创建工具栏
     */
    private VBox createToolBar() {
        VBox toolbar = new VBox(10);
        
        // 第一行：主操作按钮
        HBox row1 = new HBox(10);
        Button rectButton = new Button("Rectangle");
        Button ellipseButton = new Button("Ellipse");
        Button diamondButton = new Button("Diamond");
        ColorPicker colorPicker = new ColorPicker(currentColor);
        TextField textField = new TextField();
        textField.setPromptText("Label");
        
        // 新增：连接线样式选择器
        lineStyleComboBox = new ComboBox<>();
        lineStyleComboBox.getItems().addAll(LineStyle.values());
        lineStyleComboBox.setValue(currentLineStyle);
        
        // 新增：连接线颜色选择器
        this.lineColorPicker = new ColorPicker(lineColor); // 使用 this 明确赋值类字段
        
        // 新增：连接线粗细调节滑块
        this.lineWidthSlider = new Slider(1, 10, lineWidth);
        lineWidthSlider.setMajorTickUnit(1);
        lineWidthSlider.setShowTickLabels(true);
        
        // 添加更精确的连接线粗细调节滑块事件处理
        lineWidthSlider.valueProperty().addListener((obs, oldVal, newVal) -> {
            if (selectedLine != null) {
                // 清除图形选择，确保不会影响图形组件边框
                selectedShape = null;
                System.out.println("New line width: " + newVal);
                selectedLine.setStrokeWidth(newVal.doubleValue());
                redrawCanvas();
            }
        });

        // 添加按钮事件处理
        rectButton.setOnAction(e -> {
            currentShapeType = ShapeType.RECTANGLE;
            shouldCreateShape = true;
            System.out.println("[DEBUG] 设置 shouldCreateShape = true (矩形)");
        });
        ellipseButton.setOnAction(e -> {
            currentShapeType = ShapeType.ELLIPSE;
            shouldCreateShape = true;
            System.out.println("[DEBUG] 设置 shouldCreateShape = true (椭圆)");
        });
        diamondButton.setOnAction(e -> {
            currentShapeType = ShapeType.DIAMOND;
            shouldCreateShape = true;
            System.out.println("[DEBUG] 设置 shouldCreateShape = true (菱形)");
        });
        
        // 添加颜色选择器事件处理
        colorPicker.setOnAction(e -> {
            currentColor = colorPicker.getValue();
            if (selectedShape != null) {
                selectedShape.setColor(currentColor);
                redrawCanvas();
            }
        });
        // 添加颜色选择器事件处理
        lineColorPicker.setOnAction(e -> {
            if (selectedLine != null) {
                selectedLine.setLineColor(lineColorPicker.getValue());
                redrawCanvas();
            }
        });

        // 添加文本输入处理
        textField.setOnAction(e -> {
            if (selectedShape != null) {
                selectedShape.setText(textField.getText());
                redrawCanvas();
            }
        });

        // 添加焦点变化监听器，确保在失去焦点时也能更新文本
        textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
            if (!isNowFocused && selectedShape != null) {
                selectedShape.setText(textField.getText());
                redrawCanvas();
            }
        });

        // 第一行加入主操作按钮
        row1.getChildren().addAll(
            rectButton, ellipseButton, diamondButton,
            colorPicker, textField
        );
        
        // 第二行：连接线控件
        HBox row2 = new HBox(10);
        row2.getChildren().addAll(
            new Label("线型:"), lineStyleComboBox,
            new Label("线条颜色:"), lineColorPicker,
            new Label("线条粗细:"), lineWidthSlider
        );
        
        // 新增：文件操作按钮
        HBox row3 = new HBox(10);
        Button saveButton = new Button("保存");
        Button loadButton = new Button("导入");
        Button exportButton = new Button("导出");
        
        // 保存按钮点击事件（占位符）
        saveButton.setOnAction(e -> {
            saveToFile();
        });
        
        // 导入按钮点击事件（占位符）
        loadButton.setOnAction(e -> {
            loadFromFile();
        });
        
        // 导出按钮点击事件（占位符）
        exportButton.setOnAction(e -> {
            exportToPNG();
        });
        
        // 文件操作行加入工具栏
        row3.getChildren().addAll(saveButton, loadButton, exportButton);
        
        // 工具栏加入三行
        toolbar.getChildren().addAll(row1, row2, row3);

        return toolbar;
    }
    
    // 鼠标点击事件 - 创建新形状
    private void handleMouseClicked(MouseEvent e) {
        if (e.getButton() == MouseButton.PRIMARY && shouldCreateShape) {
            shouldCreateShape = false; // 创建一次后复位
            
            Operation operation = new Operation(OperationType.ADD_SHAPE);
            switch (currentShapeType) {
                case RECTANGLE:
                    RectangleShape rect = new RectangleShape(e.getX(), e.getY(), currentColor, currentText);
                    shapes.add(rect);
                    operation.addShape(rect);
                    System.out.println("[DEBUG] 创建矩形: " + rect);
                    break;
                case ELLIPSE:
                    EllipseShape ellipse = new EllipseShape(e.getX(), e.getY(), currentColor, currentText);
                    shapes.add(ellipse);
                    operation.addShape(ellipse);
                    System.out.println("[DEBUG] 创建椭圆: " + ellipse);
                    break;
                case DIAMOND:
                    DiamondShape diamond = new DiamondShape(e.getX(), e.getY(), currentColor, currentText);
                    shapes.add(diamond);
                    operation.addShape(diamond);
                    System.out.println("[DEBUG] 创建菱形: " + diamond);
                    break;
            }
            history.push(operation);
            redrawCanvas();
        }
    }
    
    /**
     * 创建图形库面板
     */
    private VBox createShapeLibrary() {
        VBox shapeLibrary = new VBox(10);
        Label libraryLabel = new Label("常用流程图元素:");
        Button startEndButton = new Button("开始/结束");
        Button inputOutputButton = new Button("输入/输出");
        
        // 开始/结束按钮点击事件
        startEndButton.setOnAction(e -> {
            Operation operation = new Operation(OperationType.ADD_SHAPE);
            // 创建一个表示开始/结束的椭圆
            EllipseShape start = new EllipseShape(100, 100, Color.LIGHTGREEN, "开始");
            EllipseShape end = new EllipseShape(100, 200, Color.LIGHTCORAL, "结束");
            shapes.add(start);
            shapes.add(end);
            operation.addShape(start);
            operation.addShape(end);
            history.push(operation);
            redrawCanvas();
        });
        
        // 输入/输出按钮点击事件
        inputOutputButton.setOnAction(e -> {
            Operation operation = new Operation(OperationType.ADD_SHAPE);
            // 创建一个表示输入/输出的菱形
            DiamondShape input = new DiamondShape(300, 100, Color.LIGHTBLUE, "输入数据");
            DiamondShape output = new DiamondShape(300, 200, Color.LIGHTYELLOW, "输出结果");
            shapes.add(input);
            shapes.add(output);
            operation.addShape(input);
            operation.addShape(output);
            history.push(operation);
            redrawCanvas();
        });
        
        shapeLibrary.getChildren().addAll(libraryLabel, startEndButton, inputOutputButton);
        return shapeLibrary;
    }
    
    /**
     * 设置画布事件处理
     */
    private void setupCanvasEvents() {
        GraphicsContext gc = canvas.getGraphicsContext2D();

        // 鼠标按下事件 - 用于拖拽移动
        canvas.setOnMousePressed((MouseEvent e) -> {
            selectedLine=null;
            if (e.getButton() == MouseButton.PRIMARY) {
                wasDragging = false;
                
                if (e.isControlDown()) {
                    isMultiSelecting = true;
                    selectionStartX = e.getX();
                    selectionStartY = e.getY();
                    selectionEndX = e.getX();
                    selectionEndY = e.getY();
                    multiSelection.clear(); // 开始框选前清空上一次的多选
                } else if (!multiSelection.isEmpty() && !isMultiSelecting) {
                    // 如果已经有多选且不在框选模式下，记录拖动起点以统一移动
                    dragStartX = e.getX();
                    dragStartY = e.getY();
                } else {
                    // 单击选择新形状（此时清除之前的多选）
                    selectShape(e.getX(), e.getY());
                    if (selectedShape != null) {
                        dragStartX = e.getX();
                        dragStartY = e.getY();
                    }
                    multiSelection.clear(); // 添加此行，确保单击时清除多选
                }
            }
        });

        // 鼠标拖动事件 - 用于拖拽移动和多选框
        canvas.setOnMouseDragged((MouseEvent e) -> {
            if (e.getButton() == MouseButton.PRIMARY) {
                wasDragging = true;
                
                if (!multiSelection.isEmpty()) {
                    double deltaX = e.getX() - dragStartX;
                    double deltaY = e.getY() - dragStartY;
                    
                    for (DrawableShape shape : multiSelection) {
                        shape.move(deltaX, deltaY);
                    }
                    
                    dragStartX = e.getX();
                    dragStartY = e.getY();
                    // 新增：更新所有连接线
                    connectionManager.updateAll(null);
                    redrawCanvas();
                } else if (selectedShape != null && !isMultiSelecting) {
                    // 单个图形拖动逻辑
                    double deltaX = e.getX() - dragStartX;
                    double deltaY = e.getY() - dragStartY;
                    selectedShape.move(deltaX, deltaY);
                    dragStartX = e.getX();
                    dragStartY = e.getY();
                    // 新增：更新与当前图形有关的连接线
                    connectionManager.updateAll(selectedShape);
                    redrawCanvas();
                } else if (isMultiSelecting) {
                    // 更新多选框
                    selectionEndX = e.getX();
                    selectionEndY = e.getY();
                    redrawCanvas();
                }
            }
        });

        // 鼠标释放事件 - 完成拖拽或创建多选框
        canvas.setOnMouseReleased((MouseEvent e) -> {
            if (e.getButton() == MouseButton.PRIMARY) {
                if (!multiSelection.isEmpty()) {
                    // 记录统一移动操作
                    Operation operation = new Operation(OperationType.MOVE_SHAPE);
                    for (DrawableShape shape : multiSelection) {
                        operation.addShape(shape);
                        operation.saveNewState(shape);
                    }
                    history.push(operation);
                    
                    // 拖动结束后自动退出多选状态
                    multiSelection.clear();
                    redrawCanvas();
                } else if (selectedShape != null && !isMultiSelecting) {
                    double dragDistance = Math.hypot(e.getX() - dragStartX, e.getY() - dragStartY);
                    // 只有移动距离大于一定值才算作拖动
                    if (dragDistance > 5) {
                        // 记录移动操作
                        Operation operation = new Operation(OperationType.MOVE_SHAPE);
                        operation.addShape(selectedShape);
                        operation.saveNewState(selectedShape);
                        history.push(operation);
                    }
                } else if (isMultiSelecting) {
                    // 完成多选框选择
                    selectShapesInRegion();
                    isMultiSelecting = false;
                    // 清除选择框（新增）
                    selectionStartX = 0;
                    selectionStartY = 0;
                    selectionEndX = 0;
                    selectionEndY = 0;
                    redrawCanvas();
                }
            }
        });

        // 鼠标点击事件 - 创建新形状或清空选择
        canvas.setOnMouseClicked(e -> {
            System.out.println("[DEBUG] 鼠标点击事件已触发");
            System.out.println("Canvas focused: " + canvas.isFocused());
            if (e.getButton() == MouseButton.PRIMARY && !wasDragging) {
                boolean clickedOnShape = false;
                
                for (int i = shapes.size() - 1; i >= 0; i--) {
                    if (shapes.get(i).contains(e.getX(), e.getY())) {
                        clickedOnShape = true;
                        selectShape(e.getX(), e.getY());
                        
                        // 检查是否点击了连接点
                        ConnectionPoint point = shapes.get(i).getSelectedConnectionPoint(e.getX(), e.getY());
                        if (point != null) {
                            if (isCreatingConnection) {
                                // 如果已经在创建模式，尝试创建连接线
                                tryCreateConnection(point);
                            } else {
                                // 否则进入创建模式
                                startConnectionMode(point);
                                redrawCanvas();
                            }
                        } else {
                            // 如果未点击连接点但点击了图形，则退出连接线创建模式
                            if (isCreatingConnection) {
                                cancelConnectionMode();
                                redrawCanvas();
                            }
                            
                            // 新增：如果没有点击到任何图形，清空 selectedLine
                            if (!clickedOnShape) {
                                selectedLine = null;
                            }
                        }
                        break;
                    }
                }
                
                // 新增：检查是否点击了连接线
                for (ConnectionLine line : connectionManager.getConnections()) {
                    if (isClickOnLine(line, e.getX(), e.getY())) {
                        selectedLine = line;
                        // 清除图形选择
                        selectedShape = null;
                        multiSelection.clear();
                        // 进入连接线编辑模式
                        System.out.println("[DEBUG] 点击了连接线，进入编辑模式");
                        // 更新颜色选择器为当前连接线颜色
                        lineColorPicker.setValue(line.getLineColor()); // 使用 getLineColor() 方法获取连接线颜色
                        // 更新粗细调节滑块为当前连接线粗细
                        lineWidthSlider.setValue(line.getStrokeWidth()); // 使用 getStrokeWidth() 方法获取连接线粗细
                        redrawCanvas();
                        return;
                    }
                }
                
                if (!clickedOnShape) {
                    selectedShape = null;
                    multiSelection.clear();
                    // 新增：取消连接线创建模式
                    if (isCreatingConnection) {
                        cancelConnectionMode();
                        redrawCanvas();
                    }
                }
                
                // 新增：触发 handleMouseClicked
                handleMouseClicked(e);
            }
            
            // 新增：触发 handleMouseClicked
            handleMouseClicked(e);
        });

        // 键盘事件处理
        canvas.setOnKeyPressed((KeyEvent e) -> {
            System.out.println("[DEBUG] 键盘事件已触发");
            switch (e.getCode()) {
                case C:
                    if (e.isControlDown()) {
                        // 复制
                        System.out.println("[DEBUG] 复制");
                        copySelection();
                        e.consume();
                    }
                    break;
                    case X:
                        if (e.isControlDown()) {
                            // 剪切
                            System.out.println("[DEBUG] 剪切");
                            copySelection();
                            deleteSelection();
                            e.consume();
                        }
                        break;
                case V:
                    if (e.isControlDown()) {
                        // 粘贴
                        System.out.println("[DEBUG] 粘贴");
                        pasteClipboard();
                        e.consume();
                    }
                    break;
                case Z:
                    if (e.isControlDown()) {
                        // 撤销
                        System.out.println("[DEBUG] 撤销");
                        undo();
                        e.consume();
                    }
                    break;
                case Y:
                    if (e.isControlDown()) {
                        // 重做
                        System.out.println("[DEBUG] 重做");
                        redo();
                        e.consume();
                    }
                    break;
                case DELETE:
                    System.out.println("[DEBUG] 删除所选");
                    if (selectedShape != null || !multiSelection.isEmpty() ||  selectedLine != null) {
                        // 删除所选
                        deleteSelection();
                        e.consume();
                    }
                    break;
            }
        });

    }
    
    // 复制当前选中的形状到剪贴板
    private void copySelection() {
        clipboard.clear();
        if (selectedShape != null) {
            clipboard.add(selectedShape.copy());
        } else if (!multiSelection.isEmpty()) {
            for (DrawableShape shape : multiSelection) {
                clipboard.add(shape.copy());
            }
        }
    }
    
    // 将剪贴板内容粘贴到画布上
    private void pasteClipboard() {
        if (!clipboard.isEmpty()) {
            Operation operation = new Operation(OperationType.ADD_SHAPE);
            multiSelection.clear();
            
            // 计算粘贴位置（略偏移以区分原位置）
            double offsetX = 20;
            double offsetY = 20;
            
            // 存储原始形状和粘贴后的形状之间的映射
            Map<DrawableShape, DrawableShape> pastedShapes = new HashMap<>();
            
            // 第一次遍历：创建所有形状并添加到画布
            for (DrawableShape shape : clipboard) {
                DrawableShape newShape = shape.copy();
                if (newShape instanceof RectangleShape) {
                    RectangleShape rect = (RectangleShape) newShape;
                    rect.x += offsetX;
                    rect.y += offsetY;
                } else if (newShape instanceof EllipseShape) {
                    EllipseShape ellipse = (EllipseShape) newShape;
                    ellipse.centerX += offsetX;
                    ellipse.centerY += offsetY;
                } else if (newShape instanceof DiamondShape) {
                    DiamondShape diamond = (DiamondShape) newShape;
                    diamond.centerX += offsetX;
                    diamond.centerY += offsetY;
                }
                shapes.add(newShape);
                operation.addShape(newShape);
                pastedShapes.put(shape, newShape);
            }
            
            // 第二次遍历：应用任何需要关联其他形状的状态（如果有的话）
            // 这里可以根据需求扩展连接线等依赖关系
            
            // 更新选择
            multiSelection.addAll(pastedShapes.values());
            selectedShape = null;
            
            // 记录操作
            history.push(operation);
            
            // 增加偏移量以便下次粘贴在不同位置
            for (DrawableShape shape : clipboard) {
                offsetX += 20;
                offsetY += 20;
            }
            
            redrawCanvas();
        }
    }
    
    // 撤销最后一次操作
    private void undo() {
        if (!history.isEmpty()) {
            Operation operation = history.pop();
            redoStack.push(operation);
            operation.restore();
            redrawCanvas();
        }
    }

    /**
     * 保存当前画布内容到 XML 文件
     */
    private void saveToFile() {
        // 创建文件选择对话框
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("保存流程图文件");
        fileChooser.getExtensionFilters().addAll(
            new FileChooser.ExtensionFilter("XML 文件", "*.xml")
        );
        
        // 显示保存文件对话框
        File selectedFile = fileChooser.showSaveDialog(null);
        if (selectedFile == null) {
            return; // 用户取消了操作
        }
        
        try {
            // 创建 XML 文档
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            
            // 创建根节点
            Element rootElement = doc.createElement("canvas");
            doc.appendChild(rootElement);
            
            // 添加图形信息
            for (DrawableShape shape : shapes) {
                Element shapeElement = shape.toXml(doc);
                rootElement.appendChild(shapeElement);
            }
            
            // 添加连接线信息
            for (ConnectionLine line : connectionManager.getConnections()) {
                Element lineElement = line.toXml(doc);
                rootElement.appendChild(lineElement);
            }
            
            // 将文档写入文件
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(selectedFile);
            
            transformer.transform(source, result);
            
            System.out.println("成功保存到 " + selectedFile.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 从 XML 文件加载画布内容
     */
    private void loadFromFile() {
        // 创建文件选择对话框
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("选择要导入的流程图文件");
        fileChooser.getExtensionFilters().addAll(
            new FileChooser.ExtensionFilter("XML 文件", "*.xml")
        );
        
        // 显示打开文件对话框
        File selectedFile = fileChooser.showOpenDialog(null);
        if (selectedFile == null) {
            return; // 用户取消了操作
        }
        
        try {
            // 读取 XML 文档
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(selectedFile);
            doc.getDocumentElement().normalize();
            
            // 清空当前画布
            shapes.clear();
            connectionManager.getConnections().clear();
            
            // 解析图形信息
            NodeList shapeNodes = doc.getElementsByTagName("shape");
            for (int i = 0; i < shapeNodes.getLength(); i++) {
                Element shapeElement = (Element) shapeNodes.item(i);
                String type = shapeElement.getAttribute("type");
                
                switch (type) {
                    case "rectangle":
                        RectangleShape rect = new RectangleShape(
                            Double.parseDouble(shapeElement.getAttribute("x")),
                            Double.parseDouble(shapeElement.getAttribute("y")),
                            Color.valueOf(shapeElement.getAttribute("color")),
                            shapeElement.getAttribute("text")
                        );
                        rect.width = Double.parseDouble(shapeElement.getAttribute("width"));
                        rect.height = Double.parseDouble(shapeElement.getAttribute("height"));
                        shapes.add(rect);
                        break;
                    case "ellipse":
                        EllipseShape ellipse = new EllipseShape(
                            Double.parseDouble(shapeElement.getAttribute("centerX")),
                            Double.parseDouble(shapeElement.getAttribute("centerY")),
                            Color.valueOf(shapeElement.getAttribute("color")),
                            shapeElement.getAttribute("text")
                        );
                        ellipse.radiusX = Double.parseDouble(shapeElement.getAttribute("radiusX"));
                        ellipse.radiusY = Double.parseDouble(shapeElement.getAttribute("radiusY"));
                        shapes.add(ellipse);
                        break;
                    case "diamond":
                        DiamondShape diamond = new DiamondShape(
                            Double.parseDouble(shapeElement.getAttribute("centerX")),
                            Double.parseDouble(shapeElement.getAttribute("centerY")),
                            Color.valueOf(shapeElement.getAttribute("color")),
                            shapeElement.getAttribute("text")
                        );
                        diamond.width = Double.parseDouble(shapeElement.getAttribute("width"));
                        diamond.height = Double.parseDouble(shapeElement.getAttribute("height"));
                        shapes.add(diamond);
                        break;
                }
            }
            
            // 读取连接线信息
            NodeList lineNodes = doc.getElementsByTagName("connection");
            for (int i = 0; i < lineNodes.getLength(); i++) {
                Element lineElement = (Element) lineNodes.item(i);
                
                // 获取起始点和终点坐标
                double startX = Double.parseDouble(lineElement.getAttribute("startX"));
                double startY = Double.parseDouble(lineElement.getAttribute("startY"));
                double endX = Double.parseDouble(lineElement.getAttribute("endX"));
                double endY = Double.parseDouble(lineElement.getAttribute("endY"));
                
                // 获取连接点方向
                String startDirection = lineElement.getAttribute("startDirection");
                String endDirection = lineElement.getAttribute("endDirection");
                
                // 查找对应的图形
                DrawableShape startShape = findShapeAt(startX, startY);
                DrawableShape endShape = findShapeAt(endX, endY);
                
                if (startShape != null && endShape != null) {
                    // 根据图形类型创建连接点
                    ConnectionPoint startPoint = findNearestConnectionPoint(startShape, startX, startY);
                    ConnectionPoint endPoint = findNearestConnectionPoint(endShape, endX, endY);
                    
                    // 强制设置正确的方向
                    if (startPoint != null && endPoint != null) {
                        // 修改这里：直接使用 ConnectionPoint 构造方法创建具有指定方向的连接点
                        if (startShape instanceof RectangleShape) {
                            RectangleShape rect = (RectangleShape) startShape;
                            if (startDirection.equals("top")) {
                                startPoint = new ConnectionPoint(rect.x + rect.width/2, rect.y, "top", rect);
                            } else if (startDirection.equals("bottom")) {
                                startPoint = new ConnectionPoint(rect.x + rect.width/2, rect.y + rect.height, "bottom", rect);
                            } else if (startDirection.equals("left")) {
                                startPoint = new ConnectionPoint(rect.x, rect.y + rect.height/2, "left", rect);
                            } else if (startDirection.equals("right")) {
                                startPoint = new ConnectionPoint(rect.x + rect.width, rect.y + rect.height/2, "right", rect);
                            }
                        } else if (startShape instanceof EllipseShape) {
                            EllipseShape ellipse = (EllipseShape) startShape;
                            if (startDirection.equals("top")) {
                                startPoint = new ConnectionPoint(ellipse.centerX, ellipse.centerY - ellipse.radiusY, "top", ellipse);
                            } else if (startDirection.equals("bottom")) {
                                startPoint = new ConnectionPoint(ellipse.centerX, ellipse.centerY + ellipse.radiusY, "bottom", ellipse);
                            } else if (startDirection.equals("left")) {
                                startPoint = new ConnectionPoint(ellipse.centerX - ellipse.radiusX, ellipse.centerY, "left", ellipse);
                            } else if (startDirection.equals("right")) {
                                startPoint = new ConnectionPoint(ellipse.centerX + ellipse.radiusX, ellipse.centerY, "right", ellipse);
                            }
                        } else if (startShape instanceof DiamondShape) {
                            DiamondShape diamond = (DiamondShape) startShape;
                            if (startDirection.equals("top")) {
                                startPoint = new ConnectionPoint(diamond.centerX, diamond.centerY - diamond.height/2, "top", diamond);
                            } else if (startDirection.equals("bottom")) {
                                startPoint = new ConnectionPoint(diamond.centerX, diamond.centerY + diamond.height/2, "bottom", diamond);
                            } else if (startDirection.equals("left")) {
                                startPoint = new ConnectionPoint(diamond.centerX - diamond.width/2, diamond.centerY, "left", diamond);
                            } else if (startDirection.equals("right")) {
                                startPoint = new ConnectionPoint(diamond.centerX + diamond.width/2, diamond.centerY, "right", diamond);
                            }
                        }
                        
                        if (endShape instanceof RectangleShape) {
                            RectangleShape rect = (RectangleShape) endShape;
                            if (endDirection.equals("top")) {
                                endPoint = new ConnectionPoint(rect.x + rect.width/2, rect.y, "top", rect);
                            } else if (endDirection.equals("bottom")) {
                                endPoint = new ConnectionPoint(rect.x + rect.width/2, rect.y + rect.height, "bottom", rect);
                            } else if (endDirection.equals("left")) {
                                endPoint = new ConnectionPoint(rect.x, rect.y + rect.height/2, "left", rect);
                            } else if (endDirection.equals("right")) {
                                endPoint = new ConnectionPoint(rect.x + rect.width, rect.y + rect.height/2, "right", rect);
                            }
                        } else if (endShape instanceof EllipseShape) {
                            EllipseShape ellipse = (EllipseShape) endShape;
                            if (endDirection.equals("top")) {
                                endPoint = new ConnectionPoint(ellipse.centerX, ellipse.centerY - ellipse.radiusY, "top", ellipse);
                            } else if (endDirection.equals("bottom")) {
                                endPoint = new ConnectionPoint(ellipse.centerX, ellipse.centerY + ellipse.radiusY, "bottom", ellipse);
                            } else if (endDirection.equals("left")) {
                                endPoint = new ConnectionPoint(ellipse.centerX - ellipse.radiusX, ellipse.centerY, "left", ellipse);
                            } else if (endDirection.equals("right")) {
                                endPoint = new ConnectionPoint(ellipse.centerX + ellipse.radiusX, ellipse.centerY, "right", ellipse);
                            }
                        } else if (endShape instanceof DiamondShape) {
                            DiamondShape diamond = (DiamondShape) endShape;
                            if (endDirection.equals("top")) {
                                endPoint = new ConnectionPoint(diamond.centerX, diamond.centerY - diamond.height/2, "top", diamond);
                            } else if (endDirection.equals("bottom")) {
                                endPoint = new ConnectionPoint(diamond.centerX, diamond.centerY + diamond.height/2, "bottom", diamond);
                            } else if (endDirection.equals("left")) {
                                endPoint = new ConnectionPoint(diamond.centerX - diamond.width/2, diamond.centerY, "left", diamond);
                            } else if (endDirection.equals("right")) {
                                endPoint = new ConnectionPoint(diamond.centerX + diamond.width/2, diamond.centerY, "right", diamond);
                            }
                        }
                        
                        if (startPoint != null && endPoint != null) {
                            connectionManager.addConnection(startPoint, endPoint);
                        }
                    }
                }
            }
            
            System.out.println("成功从 " + selectedFile.getName() + " 加载");
            redrawCanvas();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 导出当前画布内容为 PNG 图片
     */
    private void exportToPNG() {
        // 创建文件选择对话框
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("保存为 PNG 图片");
        fileChooser.getExtensionFilters().addAll(
            new FileChooser.ExtensionFilter("PNG 图片", "*.png")
        );
        
        // 显示保存文件对话框
        File selectedFile = fileChooser.showSaveDialog(null);
        if (selectedFile == null) {
            return; // 用户取消了操作
        }
        
        try {
            // 使用 JavaFX 的 snapshot 方法直接保存画布
            WritableImage image = canvas.snapshot(null, null);
            
            // 创建BufferedImage并获取像素数据
            int width = (int) image.getWidth();
            int height = (int) image.getHeight();
            BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            
            // 使用Canvas直接绘制到BufferedImage
            Canvas tempCanvas = new Canvas(width, height);
            GraphicsContext tempGC = tempCanvas.getGraphicsContext2D();
            tempGC.drawImage(image, 0, 0);
            
            // 获取Graphics对象进行像素级操作
            java.awt.Graphics2D g2d = bufferedImage.createGraphics();
            
            // 使用Java2D直接绘制图像
            javafx.scene.image.Image img = canvas.snapshot(null, null);
            if (img != null) {
                // 创建与画布大小相同的AWT图像
                BufferedImage fxImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                
                // 将JavaFX图像绘制到AWT图像中
                for (int y = 0; y < height; y++) {
                    for (int x = 0; x < width; x++) {
                        int argb = img.getPixelReader().getArgb(x, y);
                        bufferedImage.setRGB(x, y, argb);
                    }
                }
            }
            
            g2d.dispose();
            
            // 使用ImageIO写入文件
            boolean success = ImageIO.write(bufferedImage, "png", selectedFile);
            
            if (success) {
                // 显示成功提示
                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                alert.setTitle("导出成功");
                alert.setHeaderText(null);
                alert.setContentText("画布已成功导出为PNG图片: " + selectedFile.getName());
                alert.showAndWait();
            } else {
                // 显示失败提示
                Alert alert = new Alert(Alert.AlertType.WARNING);
                alert.setTitle("导出失败");
                alert.setHeaderText(null);
                alert.setContentText("无法导出PNG图片，请重试。");
                alert.showAndWait();
            }
        } catch (Exception e) {
            e.printStackTrace();
            // 显示错误信息
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setTitle("导出错误");
            alert.setHeaderText(null);
            alert.setContentText("导出PNG图片时发生错误: " + e.getMessage());
            alert.showAndWait();
        }
    }
    
    // 重做最后一次撤销的操作
    private void redo() {
        if (!redoStack.isEmpty()) {
            Operation operation = redoStack.pop();
            history.push(operation);
            operation.apply();
            redrawCanvas();
        }
    }
    
    // 删除当前选中的形状
    private void deleteSelection() {
        if (selectedShape != null) {
            Operation operation = new Operation(OperationType.REMOVE_SHAPE);
            operation.addShape(selectedShape);
            deleteSelectedShape();
            history.push(operation);
        } else if (!multiSelection.isEmpty()) {
            Operation operation = new Operation(OperationType.REMOVE_SHAPE);
            for (DrawableShape shape : multiSelection) {
                operation.addShape(shape);
                deleteSelectedItems();
            }
            multiSelection.clear();
            history.push(operation);
        }else if(selectedLine != null){
            System.out.println("删除连接线");
            connectionManager.removeConnection(selectedLine);
            selectedLine = null;
        }
        redrawCanvas();
    }

    private void selectShape(double x, double y) {
        // 反向遍历，确保选中最上层的形状
        for (int i = shapes.size() - 1; i >= 0; i--) {
            if (shapes.get(i).contains(x, y)) {
                selectedShape = shapes.get(i);
                multiSelection.clear();
                multiSelection.add(selectedShape);
                return;
            }
        }
        selectedShape = null;
        multiSelection.clear();
    }

    private void selectShapesInRegion() {
        // 计算选框的边界
        double minX = Math.min(selectionStartX, selectionEndX);
        double maxX = Math.max(selectionStartX, selectionEndX);
        double minY = Math.min(selectionStartY, selectionEndY);
        double maxY = Math.max(selectionStartY, selectionEndY);

        // 清除之前的多选
        multiSelection.clear();

        // 选择框内的形状
        for (DrawableShape shape : shapes) {
            double[] bounds = getShapeBounds(shape);
            if (bounds != null) {
                // 检查形状的中心点是否在选择框内
                double centerX = (bounds[0] + bounds[2]) / 2;
                double centerY = (bounds[1] + bounds[3]) / 2;
                if (centerX >= minX && centerX <= maxX && centerY >= minY && centerY <= maxY) {
                    multiSelection.add(shape);
                }
            }
        }

        // 如果只有一个形状被选中，设置为单选模式
        if (multiSelection.size() == 1) {
            selectedShape = multiSelection.get(0);
        } else {
            selectedShape = null;
        }
    }

    private void redrawCanvas() {
        GraphicsContext gc = canvas.getGraphicsContext2D();
        // 清除整个画布
        gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
        for (DrawableShape shape : shapes) {
            shape.draw(gc);
            // 在连接线创建模式下始终显示连接点
            if (isCreatingConnection || (selectedShape != null && selectedShape == shape)) {
                shape.drawConnectionPoints(gc);
            }
        }
        
        // 新增：绘制所有连接线
        connectionManager.drawAll(gc);
        
        // 如果有选中的形状，在其周围绘制选择框
        if (selectedShape != null) {
            gc.setStroke(Color.BLUE);
            gc.setLineWidth(2);
            // 获取选中形状的边界框
            double[] bounds = getShapeBounds(selectedShape);
            if (bounds != null) {
                gc.strokeRect(bounds[0], bounds[1], bounds[2] - bounds[0], bounds[3] - bounds[1]);
            }
        }
        
        // 如果有多个选中形状，绘制统一的选择框
        if (multiSelection.size() > 1) {
            // 找出所有选中形状的边界框
            double minX = Double.MAX_VALUE;
            double maxX = Double.MIN_VALUE;
            double minY = Double.MAX_VALUE;
            double maxY = Double.MIN_VALUE;
            
            for (DrawableShape shape : multiSelection) {
                double[] bounds = getShapeBounds(shape);
                if (bounds != null) {
                    minX = Math.min(minX, bounds[0]);
                    maxX = Math.max(maxX, bounds[2]);
                    minY = Math.min(minY, bounds[1]);
                    maxY = Math.max(maxY, bounds[3]);
                }
            }
            
            if (minX < maxX && minY < maxY) {
                gc.setStroke(Color.BLUE);
                gc.setLineWidth(2);
                gc.strokeRect(minX, minY, maxX - minX, maxY - minY);
            }
        }
        
        // 如果正在多选框选中，绘制选择框
        if (isMultiSelecting) {
            gc.setStroke(Color.DODGERBLUE);
            gc.setFill(Color.rgb(173, 216, 230, 0.5));
            gc.setLineWidth(2);
            double width = selectionEndX - selectionStartX;
            double height = selectionEndY - selectionStartY;
            gc.strokeRect(selectionStartX, selectionStartY, width, height);
            gc.fillRect(selectionStartX, selectionStartY, width, height);
        }
    }

    public void startConnectionMode(ConnectionPoint startPoint) {
        this.isCreatingConnection = true;
        this.connectionStartPoint = startPoint;
    }

    public void tryCreateConnection(ConnectionPoint endPoint) {
        if (isCreatingConnection && connectionStartPoint != null && endPoint != null) {
            connectionManager.addConnection(connectionStartPoint, endPoint);
            isCreatingConnection = false;
            connectionStartPoint = null;
            redrawCanvas();
        }
    }

    public void cancelConnectionMode() {
        isCreatingConnection = false;
        connectionStartPoint = null;
    }

    // 新增：判断鼠标是否点击在连接线上
    private boolean isClickOnLine(ConnectionLine line, double x, double y) {
        Point2D start = line.getStart().getPosition();
        Point2D end = line.getEnd().getPosition();
        
        // 计算点到直线的距离
        double distance = Math.abs((end.getY() - start.getY()) * x - (end.getX() - start.getX()) * y + end.getX() * start.getY() - end.getY() * start.getX()) / 
                       Math.sqrt(Math.pow(end.getY() - start.getY(), 2) + Math.pow(end.getX() - start.getX(), 2));
        
        return distance <= 5; // 点击距离连接线 5 像素以内视为点击连接线
    }

    /**
     * 根据坐标查找最近的连接点
     * @param shape - 图形对象
     * @param x - X 坐标
     * @param y - Y 坐标
     * @return - 最近的连接点
     */
    private ConnectionPoint findNearestConnectionPoint(DrawableShape shape, double x, double y) {
        if (shape instanceof RectangleShape || shape instanceof DiamondShape || shape instanceof EllipseShape) {
            Point2D pos = new Point2D(x, y);
            List<ConnectionPoint> points = new ArrayList<>();
            
            // 根据图形类型创建连接点
            if (shape instanceof RectangleShape) {
                RectangleShape rect = (RectangleShape) shape;
                points.add(new ConnectionPoint(rect.x + rect.width/2, rect.y, "top", rect));
                points.add(new ConnectionPoint(rect.x + rect.width/2, rect.y + rect.height, "bottom", rect));
                points.add(new ConnectionPoint(rect.x, rect.y + rect.height/2, "left", rect));
                points.add(new ConnectionPoint(rect.x + rect.width, rect.y + rect.height/2, "right", rect));
            } else if (shape instanceof EllipseShape) {
                EllipseShape ellipse = (EllipseShape) shape;
                points.add(new ConnectionPoint(ellipse.centerX, ellipse.centerY - ellipse.radiusY, "top", ellipse));
                points.add(new ConnectionPoint(ellipse.centerX, ellipse.centerY + ellipse.radiusY, "bottom", ellipse));
                points.add(new ConnectionPoint(ellipse.centerX - ellipse.radiusX, ellipse.centerY, "left", ellipse));
                points.add(new ConnectionPoint(ellipse.centerX + ellipse.radiusX, ellipse.centerY, "right", ellipse));
            } else if (shape instanceof DiamondShape) {
                DiamondShape diamond = (DiamondShape) shape;
                points.add(new ConnectionPoint(diamond.centerX, diamond.centerY - diamond.height/2, "top", diamond));
                points.add(new ConnectionPoint(diamond.centerX, diamond.centerY + diamond.height/2, "bottom", diamond));
                points.add(new ConnectionPoint(diamond.centerX - diamond.width/2, diamond.centerY, "left", diamond));
                points.add(new ConnectionPoint(diamond.centerX + diamond.width/2, diamond.centerY, "right", diamond));
            }
            
            ConnectionPoint nearest = null;
            double minDistance = Double.MAX_VALUE;
            for (ConnectionPoint point : points) {
                Point2D p = point.getPosition();
                double distance = Math.hypot(p.getX() - x, p.getY() - y);
                if (distance < minDistance) {
                    minDistance = distance;
                    nearest = point;
                }
            }
            
            return nearest;
        }
        return null;
    }

    // 新增：根据坐标查找图形
    private DrawableShape findShapeAt(double x, double y) {
        for (DrawableShape shape : shapes) {
            if (shape.contains(x, y)) {
                return shape;
            }
        }
        return null;
    }
    
    /**
     * 获取指定类型的图形列表
     * @param type 图形类型
     * @return 指定类型的图形列表
     */
    public <T extends DrawableShape> List<T> getShapesOfType(Class<T> type) {
        return shapes.stream()
                .filter(shape -> type.isInstance(shape))
                .map(type::cast)
                .collect(Collectors.toList());
    }
    
    // 获取形状的边界框
    private double[] getShapeBounds(DrawableShape shape) {
        if (shape instanceof RectangleShape) {
            RectangleShape rect = (RectangleShape) shape;
            return new double[]{rect.x, rect.y, rect.x + rect.width, rect.y + rect.height};
        } else if (shape instanceof EllipseShape) {
            EllipseShape ellipse = (EllipseShape) shape;
            return new double[]{ellipse.centerX - ellipse.radiusX, ellipse.centerY - ellipse.radiusY, 
                                ellipse.centerX + ellipse.radiusX, ellipse.centerY + ellipse.radiusY};
        } else if (shape instanceof DiamondShape) {
            DiamondShape diamond = (DiamondShape) shape;
            return new double[]{diamond.centerX - diamond.width/2, diamond.centerY - diamond.height/2,
                                diamond.centerX + diamond.width/2, diamond.centerY + diamond.height/2};
        }
        return null;
    }

    public void deleteSelectedItems() {
        for (DrawableShape shape : multiSelection) {
            deleteSelectedShape(shape);
        }
        redrawCanvas();
    }

    public void deleteSelectedShape() {
        if (selectedShape != null) {
            // 移除与该图形相关的所有连接线
            List<ConnectionLine> linesToRemove = new ArrayList<>();
            for (ConnectionLine line : connectionManager.getAllConnections()) {
                if (line.getStart().getOwner() == selectedShape ||
                    line.getEnd().getOwner() == selectedShape) {
                    linesToRemove.add(line);
                }
            }

            // 从连接管理器中移除相关连接线
            for (ConnectionLine line : linesToRemove) {
                connectionManager.removeConnection(line);
            }

            // 从图形列表中移除选中的图形
            shapes.remove(selectedShape);
            selectedShape = null;
            redrawCanvas();
        }
    }
public void deleteSelectedShape(DrawableShape shape){
    List<ConnectionLine> linesToRemove = new ArrayList<>();
    for (ConnectionLine line : connectionManager.getAllConnections()) {
        if (line.getStart().getOwner() == shape ||
                line.getEnd().getOwner() == shape) {
            linesToRemove.add(line);
        }
    }
    // 从连接管理器中移除相关连接线
    for (ConnectionLine line : linesToRemove) {
        connectionManager.removeConnection(line);
    }

    shapes.remove(shape);
}
    public static void main(String[] args) {
        launch(args);
    }
}